import os
import json
import re
from datetime import datetime
from typing import Dict, List, Any, Optional
from pathlib import Path
from langchain_ollama import OllamaLLM
from flask_cors import CORS
class LLMReportGenerator:
    """LLM报告生成器 - 综合分析异常处理结果并生成报告"""
    
    def __init__(self):
        """初始化报告生成器"""
        self.llm = OllamaLLM(base_url="http://127.0.0.1:11434", model="deepseek-r1:1.5b")
        
        # 定义相关目录路径
        self.kylin_trace_dir = "kylin_trace"
        self.agent_mcp_dir = "agent-mcp"
        self.ansible_dir = os.path.join(self.agent_mcp_dir, "Ansible")
        self.ansible_kylin_dir = "ansible_python/python/ansible_kylin"
        
    def generate_comprehensive_report(self) -> str:
        """生成综合分析报告"""
        try:
            # 1. 收集所有相关数据
            data_collection = self._collect_all_data()
            
            # 2. 构建LLM提示词
            prompt = self._build_analysis_prompt(data_collection)
            
            # 3. 调用LLM生成报告
            report = self.llm.invoke(prompt)
            
            # 4. 格式化报告
            formatted_report = self._format_report(report)
            
            return formatted_report
            
        except Exception as e:
            return f"报告生成失败: {str(e)}"
    
    def _collect_all_data(self) -> Dict[str, Any]:
        """收集所有相关数据"""
        data = {
            "anomaly_data": self._get_anomaly_data(),
            "trace_data": self._get_trace_data(),
            "llm_analysis": self._get_llm_analysis_data(),
            "rule_engine_data": self._get_rule_engine_data(),
            "ansible_scripts": self._get_latest_ansible_scripts(),
            "optimization_results": self._get_latest_optimization_results()
        }
        return data
    
    def _get_anomaly_data(self) -> Dict[str, Any]:
        """获取异常数据（从boss_node.py的全局变量或模拟数据）"""
        try:
            # 这里可以从boss_node.py的RESULT全局变量获取
            # 或者从Redis/数据库获取最新的异常数据
            return {
                "source": "boss_node_analysis",
                "timestamp": datetime.now().isoformat(),
                "note": "需要从boss_node.py的RESULT变量获取实际异常数据"
            }
        except Exception as e:
            return {"error": f"获取异常数据失败: {e}"}
    
    def _get_trace_data(self) -> Dict[str, Any]:
        """获取kylin_trace目录下的trace.txt数据"""
        try:
            trace_file = os.path.join(self.kylin_trace_dir, "trace.txt")
            if os.path.exists(trace_file):
                # 读取文件的前1000行作为样本（避免文件过大）
                with open(trace_file, 'r', encoding='utf-8') as f:
                    lines = f.readlines()[:1000]
                    content = ''.join(lines)
                
                return {
                    "file_path": trace_file,
                    "file_size": os.path.getsize(trace_file),
                    "sample_content": content,
                    "total_lines": len(lines)
                }
            else:
                return {"error": "trace.txt文件不存在"}
        except Exception as e:
            return {"error": f"读取trace.txt失败: {e}"}
    
    def _get_llm_analysis_data(self) -> Dict[str, Any]:
        """获取LLM分析数据"""
        try:
            # 分析llm_analyzer.py的处理逻辑和结果
            return {
                "analyzer_type": "LLM分析器",
                "confidence_threshold": 0.8,
                "processing_method": "低置信度异常处理",
                "note": "分析llm_analyzer.py的处理结果"
            }
        except Exception as e:
            return {"error": f"获取LLM分析数据失败: {e}"}
    
    def _get_rule_engine_data(self) -> Dict[str, Any]:
        """获取规则引擎数据"""
        try:
            # 分析rule_engine.py的处理逻辑和结果
            return {
                "engine_type": "规则引擎",
                "processing_method": "高置信度异常处理",
                "script_selection": "基于异常类型和关键词匹配",
                "note": "分析rule_engine.py的处理结果"
            }
        except Exception as e:
            return {"error": f"获取规则引擎数据失败: {e}"}
    
    def _get_latest_ansible_scripts(self) -> List[Dict[str, Any]]:
        """获取Ansible目录下最新时间目录的脚本"""
        try:
            # 获取最新时间目录
            latest_dir = self._get_latest_timestamp_dir(self.ansible_dir)
            if not latest_dir:
                return []
            
            scripts = []
            script_dir = os.path.join(self.ansible_dir, latest_dir)
            
            if os.path.exists(script_dir):
                for file in os.listdir(script_dir):
                    if file.endswith('.sh'):
                        script_path = os.path.join(script_dir, file)
                        script_content = self._read_file_content(script_path)
                        
                        scripts.append({
                            "name": file,
                            "path": script_path,
                            "content": script_content,
                            "timestamp_dir": latest_dir
                        })
            
            return scripts
        except Exception as e:
            return [{"error": f"获取Ansible脚本失败: {e}"}]
    
    def _get_latest_optimization_results(self) -> Dict[str, Any]:
        """获取ansible_kylin目录下最新文件夹的优化结果"""
        try:
            # 获取最新时间目录
            latest_dir = self._get_latest_timestamp_dir(self.ansible_kylin_dir)
            if not latest_dir:
                return {"error": "未找到优化结果目录"}
            
            result_dir = os.path.join(self.ansible_kylin_dir, latest_dir)
            results = {
                "timestamp_dir": latest_dir,
                "result_path": result_dir,
                "files": {}
            }
            
            if os.path.exists(result_dir):
                for file in os.listdir(result_dir):
                    if file.endswith('.txt'):
                        file_path = os.path.join(result_dir, file)
                        content = self._read_file_content(file_path)
                        results["files"][file] = content
            
            return results
        except Exception as e:
            return {"error": f"获取优化结果失败: {e}"}
    
    def _get_latest_timestamp_dir(self, base_dir: str) -> Optional[str]:
        """获取指定目录下最新的时间戳目录"""
        try:
            if not os.path.exists(base_dir):
                return None
            
            # 获取所有数字命名的目录
            dirs = [d for d in os.listdir(base_dir) 
                   if os.path.isdir(os.path.join(base_dir, d)) and d.isdigit()]
            
            if not dirs:
                return None
            
            # 按数字排序，返回最新的
            return sorted(dirs, reverse=True)[0]
        except Exception:
            return None
    
    def _read_file_content(self, file_path: str, max_lines: int = 100) -> str:
        """读取文件内容（限制行数避免过大）"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                lines = f.readlines()[:max_lines]
                content = ''.join(lines)
                if len(lines) == max_lines:
                    content += f"\n... (文件过大，仅显示前{max_lines}行)"
                return content
        except Exception as e:
            return f"读取文件失败: {e}"
    
    def _build_analysis_prompt(self, data: Dict[str, Any]) -> str:
        """构建LLM分析提示词"""
        prompt = f"""
你是一个专业的系统运维分析师，需要基于以下数据生成一份综合分析报告。

## 数据来源分析

### 1. 异常数据
{json.dumps(data.get('anomaly_data', {}), ensure_ascii=False, indent=2)}

### 2. 系统追踪数据 (kylin_trace/trace.txt)
{json.dumps(data.get('trace_data', {}), ensure_ascii=False, indent=2)}

### 3. LLM分析器处理结果
{json.dumps(data.get('llm_analysis', {}), ensure_ascii=False, indent=2)}

### 4. 规则引擎处理结果
{json.dumps(data.get('rule_engine_data', {}), ensure_ascii=False, indent=2)}

### 5. Ansible调优脚本
脚本数量: {len(data.get('ansible_scripts', []))}
脚本详情:
"""
        
        for script in data.get('ansible_scripts', []):
            prompt += f"""
- 脚本名称: {script.get('name', 'N/A')}
- 脚本内容:
{script.get('content', 'N/A')}
"""
        
        prompt += f"""
### 6. 优化执行结果
{json.dumps(data.get('optimization_results', {}), ensure_ascii=False, indent=2)}

## 分析要求

请基于以上数据，生成一份包含以下四个部分的Markdown格式报告：

### 1. 异常类型
- 识别系统出现的异常类型
- 分析异常的发生时间和持续时间
- 评估异常的严重程度和影响范围

### 2. 根因分析
- 基于trace.txt和异常数据深入分析根本原因
- 分析异常产生的技术原因和业务影响
- 识别相关的系统组件和依赖关系

### 3. 解决方案
- 分析LLM分析器和规则引擎选择的处理方案
- 解释Ansible脚本中各个命令的作用和调优原理
- 评估解决方案的有效性和适用性

### 4. 总结
- 总结整个异常处理流程的效果
- 分析优化前后的性能对比
- 提出后续的改进建议和预防措施

请严格按照Markdown格式输出，确保报告结构清晰、内容详实、分析深入。
"""
        
        return prompt
    
    def _format_report(self, report: str) -> str:
        """格式化报告输出"""
        # 添加报告头部信息
        header = f"""# 系统异常处理综合分析报告

**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
**分析工具**: LLM智能分析系统
**报告类型**: 综合异常处理分析

---

"""
        
        # 清理和格式化报告内容
        cleaned_report = self._clean_report_content(report)
        
        return header + cleaned_report
    
    def _clean_report_content(self, content: str) -> str:
        """清理报告内容"""
        # 移除可能的markdown代码块标记
        content = re.sub(r'```markdown\s*', '', content)
        content = re.sub(r'```\s*$', '', content)
        
        # 移除思考内容（<think>标签及其内容）
        content = re.sub(r'<think>.*?</think>', '', content, flags=re.DOTALL)
        
        # 移除单独的思考标签
        content = re.sub(r'<think>', '', content)
        content = re.sub(r'</think>', '', content)
        
        # 确保标题格式正确（更精确的匹配，避免冲突）
        # 处理标题格式：确保#号后面有且仅有一个空格
        content = re.sub(r'^(#{1,6})\s*(.+)$', r'\1 \2', content, flags=re.MULTILINE)
        
        # 修复可能出现的多余空格
        content = re.sub(r'^(#{1,6})\s+', r'\1 ', content, flags=re.MULTILINE)
        
        # 移除多余的空行
        content = re.sub(r'\n\s*\n\s*\n', '\n\n', content)
        
        return content.strip()

def generate_report():
    """生成报告的便捷函数"""
    generator = LLMReportGenerator()
    return generator.generate_comprehensive_report()

from flask import Flask, jsonify
import threading

# 创建Flask应用
app = Flask(__name__)

@app.route('/allUpdatePaper', methods=['GET'])
def get_praise_markdown():
    """返回Markdown格式的综合分析报告"""
    try:
        # 生成报告
        report = generate_report()
        print(report)
        return report
    except Exception as e:
        return f"报告生成失败: {str(e)}", 500

def start_flask_server():
    """启动Flask服务器"""


def report_llm_1():
    """生成报告并启动Flask服务器"""
    try:
        # 生成报告
        report = generate_report()
        print("报告生成完成")
        
        # 启动Flask服务器
        print("启动Flask服务器，监听端口9000...")
        server_thread = threading.Thread(target=start_flask_server, daemon=True)
        server_thread.start()
        
        print("Flask服务器已启动，前端可通过 http://192.168.31.56:5000/allUpdatePaper 获取报告")
        
    except Exception as e:
        print(f"启动失败: {e}")

if __name__ == "__main__":
    # 测试报告生成
    report = generate_report()
    print(report)
    CORS(app)
    app.run(host='0.0.0.0', port=5000, debug=False)
    # print(report)


# def report_llm_2():
#      # 测试报告生成
#     # report = generate_report()
#     CORS(app)
#     app.run(host='0.0.0.0', port=5000, debug=False)
#     # print(report)
